import time, types, pickle, re, copy

AREA_FILENAME_REGEXP = re.compile("^\w+\.area$")

def areas_command( ch, args ):
  """
  Usage:
  areas
  
  Display a list of areas.
  """
  buf = "${blue,bold}Areas:\n${reset}"
  buf += "%-12s | %-3s\n" % ('Zone Name','ZID')
  for a in ch.d.server.areas:
    buf += "%-12s - %-3d\n" % ( a.name, a.zid )
  ch.toSelf(buf.strip())

def instances_command( ch, args ):
  """
  Usage:
  areas
  
  Display a list of instances.
  """
  buf  = " ${blue,bold}------- ${white,bold}Instances ${blue,bold}--------\n"
  buf += "| ${white,bold}%-12s ${blue,bold}|${white,bold} %-3s ${blue,bold}|${white,bold} %-3s${blue,bold} |\n" % ('Zone Name','ZID','IID')
  buf += " ${blue,bold}--------------------------\n"
  for a in ch.d.server.instances:
    buf += "| ${white}%-12s ${blue,bold}|${white} %-3d ${blue,bold}|${white} %-3d${blue,bold} |\n" % ( a.name, a.zid, a.iid )
  buf += " ${blue,bold}--------------------------${reset}"
  ch.toSelf(buf)

def createarea_command( ch, args ):
  """
  Usage:
  createarea <name>
  
  Creates a new area named name.
  """
  if len(args[0]) > 0:
    if not AREA_FILENAME_REGEXP.match(args[0]):
      ch.toSelf("Area names can only contain numbers letters and underscore characters.")
      return
    newArea        = Area()
    newArea.name   = args[0]
    newArea.server = ch.d.server
    found = False
    # find a zone id
    if newArea.server.areas == []:
      found = True
      newArea.zid = 0
      newArea.server.areas.append(newArea)
    else:
      n = 0
      usedIDs = [zid for a.zid in newArea.server.areas]
      while not found and n <= 9999:
        if n not in userIDs:
          found = True
          newArea.zid = n
          newArea.server.areas.append(newArea)
        else:
          n += 1
    if found:
      newArea.save()
      ch.toSelf("New area %s created." % newArea.name)
      return
    else:
      ch.toSelf("Couldn't create new area!")
      return
  else:
    ch.toSelf("You must supply a name.")
    return

def goinstance_command( ch, args ):
    """
    Usage:
    goinstance <id>
    
    Transports you to an area with the given id.
    """
    # find the instance
    try:
        iid = int(args[0])
        instance = ch.d.server.instances[iid]
    except Exception, e:
        ch.toSelf("Error: %s" % e)
        return
    
    # if there are no rooms we must create one
    if not instance.rooms:
        room = Room()
        room.area = instance
        instance.rooms.append(room)
    # ship them off to the first room
    ch.goto( iid, 0 )
        
    
class Area:
  """
  Class definition for a Area
  """
  def __init__(self,params=None):
    # Saved
    self.zid        = None # Prototypal zone identifier
    self.name       = "A new zone"
    self.rooms      = []
    
    # Not saved
    self.iid    = None # Instance ID
    self.server = None # the server
    self.ch_list = []
    
    if params is not None:
      self.set(params)

  
  def set(self,params):
    if type(params) is types.DictType:
      for p in params.keys():
        try:
          setattr(self,p,params[p])
        except:
          print "Area.set: Couldn't set p! (%s)" % p
    else:
      for p in params.__dict__.keys():
        try:
          t = type(getattr(params,p))
          try:
            setattr(self,p,getattr(params,p))
          except:
            print "Area.set: Couldn't set %s with %s" (p,getattr(params,p))
        except:
          print "Area.set: Couldn't set p! (%s)[%s]" % (p,type(p))
  
  
  def __getstate__(self):
    return {
            "zid":self.zid,
            "name":self.name,
            "rooms":self.rooms,
            "resetTicks":self.resetTicks
            }
     
            
  def save(self):
    print "Saving area '%s'..." % self.name
    a = open("areas/%s.area" % self.name, "w")
    pickle.dump(self, a)
    a.close()
  
  
  def findFreeIID(self):
    iids = [i for instance.iid in self.server.instances]
    for n in xrange(0,101):
      if n not in iids:
        return n
    return None
  
  
  def instantiate(self):
    "Makes a copy and puts it into the instance list"
    # find instances already in existance
    iid = self.findFreeIID()
    if iid is None:
      return False
    else:
      print "Instantiating %s #%d..." % (self.name,iid)
      instance = copy.deepcopy(self)
      instance.iid = iid
      instance.server = self.server
      instance.ch_list = []
      instance.server.instances.append(instance)
      return True
    

class Room:
  "Class definition for a single room"
  def __init__(self,params=None):
    # Not saved
    self.area  = None
    self.ch_list = []
    # Saved
    self.rid   = None # Room id
    self.name  = "A new room"
    self.desc  = "Description for a new room"
    self.exits = []
    pass
  
  
  def set(self,params):
    if type(params) is types.DictType:
      for p in params.keys():
        try:
          setattr(self,p,params[p])
        except:
          print "Room.set: Couldn't set p! (%s)" % p
    else:
      for p in params.__dict__.keys():
        try:
          t = type(getattr(params,p))
          try:
            setattr(self,p,getattr(params,p))
          except:
            print "Room.set: Couldn't set %s with %s" (p,getattr(params,p))
        except:
          print "Room.set: Couldn't set p! (%s)[%s]" % (p,type(p))
  
  def __getstate__(self):
    return {
      "name":self.name,
      "desc":self.desc,
      "exits":self.exits
    }
    
    
class Exit:
  "Class definition for a single exit"
  def __init__(self,params=None):
    # Not saved
    self.room     = None
    # Saved
    self.keywords = [] 
    self.to       = None # The room this exit leads to
    self.states   = {
                      "open": True,
                      "closed": False,
                      "locked": False
                    }

  
  def set(self,params):
    if type(params) is types.DictType:
      for p in params.keys():
        try:
          setattr(self,p,params[p])
        except:
          print "Exit.set: Couldn't set p! (%s)" % p
    else:
      for p in params.__dict__.keys():
        try:
          t = type(getattr(params,p))
          try:
            setattr(self,p,getattr(params,p))
          except:
            print "Exit.set: Couldn't set %s with %s" (p,getattr(params,p))
        except:
          print "Exit.set: Couldn't set p! (%s)[%s]" % (p,type(p))
  
  
  def __getstate__(self):
    return {
      "keywords":self.keywords,
      "to":self.to,
      "states":self.states
    }
